﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Diagnostics;

namespace LibIpMsgNet
{
    public class TMessageBuffer
    {
        public THostSub Host;
        public int Version;
        public int PortNo;
        public ulong PacketNo;
        public ulong Command;
        public int exOffset;			// expand message offset in msgBuf
        public int dummy;
        public byte[] Buffer;

        public TMessageBuffer() 
        {
            Host = new THostSub();
            Buffer = new byte[Consts.MAX_UDPBUF];
        }

        public TMessageBuffer(TMessageBuffer org)
        {
            if (org == null)
            {
                Host = new THostSub();
                Buffer = new byte[Consts.MAX_UDPBUF];
            }
            else
            {
                this.Host = org.Host;
                this.Version = org.Version;
                this.PortNo = org.PortNo;
                this.PacketNo = org.PacketNo;
                this.Command = org.Command;
                this.Buffer = org.Buffer;
            }
        }

        public string TextMessage()
        {
            if (Buffer.Length > 0 && exOffset > 0)
            {
                byte[] text = new byte[exOffset+1];
                Array.Copy(Buffer, text, exOffset + 1);
                return Encoding.ASCII.GetString(text);
            }
            return "";
        }

    }

    public class TMessageManager
    {
        // PACKET = VERSION:PACKETNO:USERNAME:HOSTNAME:COMMAND:MSG+EXMSG
        
        public static ulong MakeMessage(out byte[] buf, ulong _packetNo, ulong command, 
            string msg, string exMsg, out int packet_len, THostSub local)
        {
            try
            {
                string str = String.Format("{0}:{1}:{2}:{3}:{4}:{5}",
                    IPMSG_DEF.IPMSG_VERSION, _packetNo, local.UserName, local.HostName, command, msg);

                if (exMsg != null && !exMsg.Equals(""))
                    str = String.Format("{0}\0{1}\0", str, exMsg);

                // here replace '\r\n' to '\n' : new line to unix
                str.Replace("\r\n", "\n");

                //if (packet_len != null)
                packet_len = str.Length;

                buf = Encoding.ASCII.GetBytes(str);

                return _packetNo;
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.StackTrace + ex.Message);

                packet_len = 0;
                buf = null;
                return 0;
            }
        }

        
        public static bool ResolveMessage(TRecvBuffer buf, ref TMessageBuffer msg)
        {
            try
            {
                int pos, lastpos;

                msg.Host.EndPoint = buf.EndPoint;

                //string str = Utils.ByteArrayToString(buf.Buffer);
                string str = Encoding.ASCII.GetString(buf.Buffer);

                // version
                pos = str.IndexOf(':', 0);
                if (pos < 0)
                    return false;
                else
                    msg.Version = Convert.ToInt32(str.Substring(0, pos));

                // check version
                if ((ulong)msg.Version != IPMSG_DEF.IPMSG_VERSION)
                    return false;

                // packetNo
                lastpos = pos;
                pos = str.IndexOf(':', lastpos + 1);
                if (pos < 0)
                    return false;
                else
                    msg.PacketNo = (ulong)Convert.ToInt64(str.Substring(lastpos + 1, pos - lastpos - 1));

                // username
                lastpos = pos;
                pos = str.IndexOf(':', lastpos + 1);
                if (pos < 0)
                    return false;
                else
                    msg.Host.UserName = str.Substring(lastpos + 1, pos - lastpos - 1);

                // hostname
                lastpos = pos;
                pos = str.IndexOf(':', lastpos + 1);
                if (pos < 0)
                    return false;
                else
                    msg.Host.HostName = str.Substring(lastpos + 1, pos - lastpos - 1);

                // command
                lastpos = pos;
                pos = str.IndexOf(':', lastpos + 1);
                if (pos < 0)
                    return false;
                else
                    msg.Command = (ulong)Convert.ToInt64(str.Substring(lastpos + 1, pos - lastpos - 1));

                // Msg
                lastpos = pos;
                pos = str.IndexOf('\0', lastpos + 1);
                if (pos < 0)
                    return false;

                msg.exOffset = pos - lastpos - 1;

                // exMsg
                int msgpos = lastpos;
                lastpos = pos;
                pos = str.IndexOf('\0', lastpos + 1);

                // copy Msg and exMsg
                if (pos >= 0)
                    msg.Buffer = Encoding.ASCII.GetBytes(str.Substring(msgpos + 1, pos - msgpos - 1));
                else
                    msg.Buffer = Encoding.ASCII.GetBytes(str.Substring(msgpos + 1, lastpos - msgpos - 1));

                return true;
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.StackTrace + ex.Message);
                return false;
            }
        }
    }
}
